package algorithm;

import it.unisa.dia.gas.jpbc.*;
import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
import it.unisa.dia.gas.plaf.jpbc.pairing.a.TypeACurveGenerator;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Random;

public class CPABESetUp {
    //系统公钥
    private CPABEPK pubKey;
    //系统主密钥
    private CPABEMK masterKey;
    //系统所使用的双线性映射
    private Pairing pairing;
    //系统的阶
    private BigInteger order;
    //选定的生成元
    private Element g;

    public CPABESetUp() {
    }

    /**
     * 系统初次使用或者是想要变更椭圆曲线参数的时候调用
     * 生成椭圆曲线的参数，并放置在params.properties中
     */
    public void curveInitiate() throws IOException {
        //椭圆曲线群160位，有限域512位
        PairingParametersGenerator generator=new TypeACurveGenerator(256,512);
        PairingParameters parameters=generator.generate();
        BufferedWriter writer=new BufferedWriter(new FileWriter("params.properties"));
        //写文件
        writer.write(parameters.toString());
        writer.close();
    }


    /**
     * 系统初始化，生成双线性映射，公钥和主密钥
     */
    public void sysInitiate(){
        pairing= PairingFactory.getPairing("params.properties");
        Field G=pairing.getG1();

        order=G.getOrder();

        //获取乘法群生成元
        g=G.newRandomElement().getImmutable();

        //生成h
        Element beta=pairing.getZr().newRandomElement().getImmutable();
        Element h=g.powZn(beta).getImmutable();

        //生成f
        Element one=pairing.getZr().newOneElement().getImmutable();
        Element reverseBeta=one.div(beta);
        Element f=g.powZn(reverseBeta.duplicate()).getImmutable();

        //生成ea
        Element alpha=pairing.getZr().newRandomElement();
        Element ea=pairing.pairing(g,g);
        ea=ea.powZn(alpha).getImmutable();
        pubKey=new CPABEPK(g,h,f,ea,order);
        masterKey=new CPABEMK(g.powZn(alpha),beta);
    }

    /**
     * 获取主公钥
     * @return 公钥类
     */
    public CPABEPK getPubKey() {
        return pubKey;
    }

    /**
     * 获取主密钥
     * @return 主密钥类
     */
    public CPABEMK getMasterKey() {
        return masterKey;
    }

    /**
     * 获取双线性映射
     * @return 双线性映射pairing类型
     */
    public Pairing getPairing() {
        return pairing;
    }

    public BigInteger getOrder() {
        return order;
    }


    public Element getG() {
        return g;
    }

}
